/**
 * 图网络分析 store
 * @author JinHui Hou
 */
import store from '@/store'
import {
  Module,
  Mutation,
  VuexModule,
  getModule,
  Action,
} from 'vuex-module-decorators'
import {
  addGraph,
  deleteGraphById,
  queryGraphByProjectId,
  queryGraphByTabId,
  renameTab,
  loadDqueryLoadStatusata,
  uploadFile,
  queryFilterPipelineByGraphId,
  addFilterPipeline,
  updateFilterPipeline,
  deleteFilterPipeline,
  queryFilterByFilterPipelineId,
  addFilter,
  updateFilter,
  deleteFilter,
  queryFilterAvailableAttributes,
  executeFilterPipeline,
  resetFilterPipeline,
  deleteItems,
  updateItems,
  queryPath,
  search,
  queryAvailableCategory,
  saveWidget,
  redo,
  undo,
  queryHeatMap,
} from '@/api/graph-analysis'
import {
  Filter,
  FilterPipeline,
} from '@/components/graph-analysis/right-drawer/data-filter/data-filter'
import { message } from 'ant-design-vue'

export interface Tab {
  id: number
  name: string
  projectId?: number
  userId?: number
  data?: { name: string }
}

@Module({ dynamic: true, namespaced: true, name: 'GraphAnalysis', store })
class GraphAnalysis extends VuexModule {
  private _projectId: number | null = null

  private _graphDirected: boolean = false // 图是否有向

  private _tableInfoHeight: number = 38 // 数据表高度

  private _tabsData: any = [] // 当前项目下所有的tab标签
  private _activeTabId: any = 0 // 当前选中的tab的id, 即 graphId

  private _graphScales: any[] = [] // 不同图的缩放大小

  private _graphFilters: FilterPipeline[] = [] // 当前项目下所有的过滤
  private _activeFilter: Filter | null = null // 当前选中过滤器名称
  private _runningFilterPipelineId = -1 // 正在运行的过滤流程id

  private _selectedTool: string = '' // 当前选择的工具

  // 箭头选择
  private _selectRadius: number = 1 // 选择工具的半径
  private _selectNeighbors: boolean = true // 是否自动选择邻居节点

  // 手型拖动
  private _dragRadius: number = 1 // 拖动工具的半径

  // 框选 套索
  private _lassoNeighbors: boolean = true // 是否自动选择邻居节点

  // 着色
  private _colorRadius: number = 1 // 着色工具的半径
  private _selectedColor: string = '#a4abfb' // 节点着色颜色

  // 格式刷
  private _formatColor: string = '#a4abfb' // 格式刷颜色
  private _formatType: string = 'both' // 格式刷范围

  // 重设颜色
  private _redrawColor: string = '#a4abfb' // 重设的颜色
  private _needRedraw: boolean = false

  // 标签设置
  private _labelIsShow: string = 'show-outer' // 标签显示方式
  private _labelFontType: string = 'self' // 标签字号类型
  private _labelFontSize: number = 12 // 标签字号
  private _labelColorType: string = 'self' // 标签颜色类型
  private _labelColor: string = '#6e80a2' // 标签颜色

  // 边设置
  private _edgeIsShow: string = 'show' // 是否显示边
  private _edgeLabelIsShow: string = 'notshow' // 是否显示边上的标签
  private _edgeColorType: string = 'self' // 边的颜色类型
  private _edgeColor: string = '#D9D9D9' // 边的颜色

  // 热区
  private _heatmapColor: string = '#a4abfb' // 热区颜色
  private _heatmapResult: any = null // 热区查询结果

  // 搜索
  private _searchResult: Array<any> = [] // 搜索到的节点

  private _isManualAction: boolean = false // 当前操作是否是用户操作（否则是undo/redo
  private _needSave: boolean = false // 是否需要保存

  private _graphInfoIsShow: boolean = false // 是否显示图概览

  private _deleteItem: boolean = false // 是否删除当前选中的节点

  private _undoRedoAction: any = null // 前进或后退的结果
  private _undoRedoStatus: string = '' // 当前状态是undo还是redo

  private _categories: any = [] // 节点分类 categories
  private _edgesClass: any = [] // 边的分类 edges
  private _loadToGraphAnalysisId: number | null = null // 由图构建分析， 加载跳转到图分析页面的 graphId
  private _loadId: number | null = null // （构建过来/载入数据）加载任务id，用于轮询进度
  private _currentTabLoadGraphDataIng: number = 1 // 当前 tab 正在加载图数据  1-没有加载数据，2-正在加载
  private _currentLoadingGraphDataTabId: number | null = null // 当前加载数据的tabId(graphId)
  private _graphAnalysisRootSize: { width: number; height: number } = {
    width: 0,
    height: 0,
  } // graph 尺寸

  private _graphAnalysisLoading: boolean = false // 图分析 loading
  private _graphAnalysisLoadingText: string = '请等待...' // 图分析 loading 文案

  private _shareAttr: any[] = [] // 图节点共有属性

  /** ====== get ====== */
  public get projectId() {
    return this._projectId
  }

  public get graphDirected() {
    return this._graphDirected
  }

  public get tableInfoHeight(): number {
    return this._tableInfoHeight
  }

  public get activeTabId(): number | null {
    return this._activeTabId
  }

  public get graphScales(): any[] {
    return this._graphScales
  }

  public get tabsData(): any {
    return this._tabsData
  }

  public get graphFilters(): FilterPipeline[] {
    return this._graphFilters
  }

  public get activeFilter(): Filter | null {
    return this._activeFilter
  }

  public get runningFilterPipelineId(): number {
    return this._runningFilterPipelineId
  }

  public get selectedTool() {
    return this._selectedTool
  }

  public get selectRadius() {
    return this._selectRadius
  }

  public get selectNeighbors() {
    return this._selectNeighbors
  }

  public get dragRadius() {
    return this._dragRadius
  }

  public get lassoNeighbors() {
    return this._lassoNeighbors
  }

  public get colorRadius() {
    return this._colorRadius
  }

  public get selectedColor() {
    return this._selectedColor
  }

  public get formatColor() {
    return this._formatColor
  }

  public get formatType() {
    return this._formatType
  }

  public get redrawColor() {
    return this._redrawColor
  }

  public get needRedraw() {
    return this._needRedraw
  }

  public get labelIsShow() {
    return this._labelIsShow
  }

  public get labelFontType() {
    return this._labelFontType
  }

  public get labelFontSize() {
    return this._labelFontSize
  }

  public get labelColorType() {
    return this._labelColorType
  }

  public get labelColor() {
    return this._labelColor
  }

  public get edgeIsShow() {
    return this._edgeIsShow
  }

  public get edgeLabelIsShow() {
    return this._edgeLabelIsShow
  }

  public get edgeColorType() {
    return this._edgeColorType
  }

  public get edgeColor() {
    return this._edgeColor
  }

  public get searchResult() {
    return this._searchResult
  }

  public get heatmapColor() {
    return this._heatmapColor
  }

  public get heatmapResult() {
    return this._heatmapResult
  }

  public get isManualAction() {
    return this._isManualAction
  }

  public get needSave() {
    return this._needSave
  }

  public get graphInfoIsShow() {
    return this._graphInfoIsShow
  }

  public get deleteItem() {
    return this._deleteItem
  }

  public get undoRedoAction() {
    return this._undoRedoAction
  }

  public get undoRedoStatus() {
    return this._undoRedoStatus
  }

  public get categories() {
    return this._categories
  }

  public get edgesClass() {
    return this._edgesClass
  }

  public get loadToGraphAnalysisId() {
    return this._loadToGraphAnalysisId
  }

  public get loadId(): number | null {
    return this._loadId
  }

  public get currentTabLoadGraphDataIng() {
    return this._currentTabLoadGraphDataIng
  }

  public get currentLoadingGraphDataTabId() {
    return this._currentLoadingGraphDataTabId
  }

  public get graphAnalysisRootSize() {
    return this._graphAnalysisRootSize
  }

  public get graphAnalysisLoading() {
    return this._graphAnalysisLoading
  }

  public get graphAnalysisLoadingText() {
    return this._graphAnalysisLoadingText
  }

  public get shareAttr() {
    return this._shareAttr
  }

  /** ====== Mutation ====== */
  @Mutation
  public graphSetProjectId(projectId: number | null) {
    this._projectId = projectId
  }

  @Mutation
  public setGraphDirected(directed: boolean) {
    this._graphDirected = directed
  }

  @Mutation
  public setTableInfoHeight(height: number) {
    this._tableInfoHeight = height
  }

  @Mutation
  public setActiveTabId(id: number | string | null) {
    this._activeTabId = id
  }

  @Mutation
  public setGraphScales(graphScales: any[]) {
    this._graphScales = graphScales
  }

  @Mutation
  public setTabsData(data: any) {
    this._tabsData = data.tabsData
    // this._activeTabId = this._tabsData[0].id  // 换其他地方处理， GraphAnalysisView.vue

    // 默认缩放比例为1
    this._graphScales = data.tabsData.map(() => {
      return {
        scaleType: 'geometry',
        scaleLevel: 1,
      }
    })
  }

  @Mutation
  public setGraphFilters(data: any) {
    this._graphFilters = data.graphFilters
  }

  @Mutation
  public setActiveFilter(value: Filter | null) {
    this._activeFilter = value
  }

  @Mutation
  public setRunningFilterPipelineId(id: number) {
    this._runningFilterPipelineId = id
  }

  @Mutation
  public setSelectedTool(tool: string) {
    this._selectedTool = tool
  }

  @Mutation
  public setSelectRadius(radius: number) {
    this._selectRadius = radius
  }

  @Mutation
  public setSelectNeighbors(value: boolean) {
    this._selectNeighbors = value
  }

  @Mutation
  public setDragRadius(value: number) {
    this._dragRadius = value
  }

  @Mutation
  public setLassoNeighbors(value: boolean) {
    this._lassoNeighbors = value
  }

  @Mutation
  public setColorRadius(value: number) {
    this._colorRadius = value
  }

  @Mutation
  public setSelectedColor(value: string) {
    this._selectedColor = value
  }

  @Mutation
  public setFormatColor(value: string) {
    this._formatColor = value
  }

  @Mutation
  public setFormatType(value: string) {
    this._formatType = value
  }

  @Mutation
  public setRedrawColor(value: string) {
    this._redrawColor = value
  }

  @Mutation
  public setNeedRedraw(value: boolean) {
    this._needRedraw = value
  }

  @Mutation
  public setLabelIsShow(value: string) {
    this._labelIsShow = value
  }

  @Mutation
  public setLabelFontType(value: string) {
    this._labelFontType = value
  }

  @Mutation
  public setLabelFontSize(value: number) {
    this._labelFontSize = value
  }

  @Mutation
  public setLabelColorType(value: string) {
    this._labelColorType = value
  }

  @Mutation
  public setLabelColor(value: string) {
    this._labelColor = value
  }

  @Mutation
  public setEdgeIsShow(value: string) {
    this._edgeIsShow = value
  }

  @Mutation
  public setEdgeLabelIsShow(value: string) {
    this._edgeLabelIsShow = value
  }

  @Mutation
  public setEdgeColorType(value: string) {
    this._edgeColorType = value
  }

  @Mutation
  public setEdgeColor(value: string) {
    this._edgeColor = value
  }

  @Mutation
  public setHeatmapColor(value: string) {
    this._heatmapColor = value
  }

  @Mutation
  public setHeatmapResult(value: any) {
    this._heatmapResult = value
  }

  @Mutation
  public setSearchResult(value: any) {
    this._searchResult = value
  }

  @Mutation
  public setManualAction(value: boolean) {
    this._isManualAction = value
  }

  @Mutation
  public setNeedSave(value: boolean) {
    this._needSave = value
  }

  @Mutation
  public setGraphInfoIsShow(value: boolean) {
    this._graphInfoIsShow = value
  }

  @Mutation
  public setDeleteItem(value: boolean) {
    this._deleteItem = value
  }

  @Mutation
  public setUndoRedoAction(value: any) {
    this._undoRedoAction = value
  }

  @Mutation
  public setUndoRedoStatus(value: string) {
    this._undoRedoStatus = value
  }

  @Mutation
  public setCategories(value: any) {
    this._categories = value
  }

  @Mutation
  public setEdges(value: any) {
    this._edgesClass = value
  }

  @Mutation
  public setCategoriesEdges(value: any) {
    this._categories = value.categories
    this._edgesClass = value.edges
  }

  @Mutation
  public setLoadToGraphAnalysisId(value: number | null) {
    this._loadToGraphAnalysisId = value
  }

  @Mutation
  public setLoadIdId(value: number | null) {
    this._loadId = value
  }

  // 当前 tab 正在加载图数据  1-没有加载数据，2-正在加载 3-加载成功， 4-加载失败
  @Mutation
  public setCurrentTabLoadGraphDataIng(value: number) {
    this._currentTabLoadGraphDataIng = value
  }

  @Mutation
  public setCurrentLoadingGraphDataTabId(value: number | null) {
    this._currentLoadingGraphDataTabId = value
  }

  @Mutation
  public setGraphAnalysisRootSize(value: { width: number; height: number }) {
    this._graphAnalysisRootSize = value
  }

  @Mutation
  public setGraphAnalysisLoading(value: boolean) {
    this._graphAnalysisLoading = value
  }

  @Mutation
  public setGraphAnalysisLoadingText(value: string) {
    this._graphAnalysisLoadingText = value
  }

  @Mutation
  public setShareAttr(value: any[]) {
    this._shareAttr = value
  }

  /** ====== Action ====== */

  /**
   * 新建标签
   * @param projectId id: 项目id
   */
  @Action
  public async addGraphTab(projectId: number) {
    const response = await addGraph({
      data: {
        projectId,
      },
    })
    if (response.data.code === 100) {
      const { id, name } = response.data.result
      this.tabsData.push({ id, name })
      message.success('添加成功!')
    }
    return response
  }

  /**
   * 删除标签
   * @param parameters { projectId: 1, graphId: 1} 图id 项目id
   */
  @Action
  public async delGraphTab(parameters: any) {
    const response: any = await deleteGraphById({
      data: {
        ...parameters,
      },
    })
    if (response.data.code === 100) {
      const deleteIndex: number = (() => {
        const tabLength: Number = this.tabsData.length
        for (let i = 0; i < tabLength; i += 1) {
          if (this.tabsData[i].id === parameters.graphId) {
            return i
          }
        }
        return -1
      })()
      if (deleteIndex > -1) {
        message.success('删除成功！')
        this.tabsData.splice(deleteIndex, 1)
      }
    } else {
      message.error('删除失败！')
    }
    return response
  }

  /**
   * 查询所有标签
   * @param projectId 项目id
   */
  @Action({ commit: 'setTabsData' })
  public async queryGraphTabs(projectId: any) {
    const response = await queryGraphByProjectId({
      data: {
        projectId,
      },
    })
    return { tabsData: response.data.result }
  }

  /**
   * 查询试图数据
   * @param parameters 图id 项目id
   */
  @Action
  public queryGraph(parameters: any) {
    const response: any = queryGraphByTabId({
      data: {
        ...parameters,
      },
    })
    return response
  }

  /**
   * tab重命名
   * @param parameters 图id 项目id 重命名name
   */
  @Action
  public async renameTab(parameters: any) {
    const response: any = await renameTab({
      data: {
        ...parameters,
      },
    })
    if (response.data.code === 100) {
      const temporary: any = this.tabsData.find(
        (tab: any) => tab.id === parameters.graphId
      )
      temporary.name = parameters.name
    } else {
      message.error('修改失败!')
    }
  }

  /**
   * 加载轮询查询状态
   * @param parameters 图id 项目id 轮询id
   */
  @Action
  public async dataLoadStatus(parameters: any) {
    const response = await loadDqueryLoadStatusata({
      data: {
        ...parameters,
      },
    })
    return response.data.result
  }

  /**
   * 上传用户数据
   */
  @Action
  public async uploadFilesList(fileName: any) {
    const response = await uploadFile({
      data: {
        file: fileName,
      },
    })
    return response.data
  }

  /**
   * 查询所有过滤
   * @param params 项目id 图id
   */
  @Action({ commit: 'setGraphFilters' })
  public async queryGraphFilterPiplines(parameters: any) {
    const response = await queryFilterPipelineByGraphId({
      data: {
        ...parameters,
      },
    })
    return { graphFilters: response.data.result }
  }

  /**
   * 添加过滤
   * @param params 项目id 图id 过滤组名称
   */
  @Action
  public async addGraphFilterPipline(parameters: any) {
    const response = await addFilterPipeline({
      data: {
        ...parameters,
      },
    })
    return response.data
  }

  /**
   * 更新过滤
   * @param params 项目id 图id 过滤组名称
   */
  @Action
  public async updateGraphFilterPipline(parameters: any) {
    const response = await updateFilterPipeline({
      data: {
        ...parameters,
      },
    })
    return response.data.success
  }

  /**
   * 删除过滤
   * @param params 项目id 图id 过滤组id
   */
  @Action
  public async deleteGraphFilterPipline(parameters: any) {
    const response = await deleteFilterPipeline({
      data: {
        ...parameters,
      },
    })
    return response.data.success
  }

  /**
   * 查询根据过滤流程查询过滤器
   * @param params 项目id 图id 过滤流程id
   */
  @Action
  public async queryGraphFilter(parameters: any) {
    const response = await queryFilterByFilterPipelineId({
      data: {
        ...parameters,
      },
    })
    return response.data.result
  }

  /**
   * 给过滤组添加过滤
   * @param params 项目id 图id 过滤流程id 过滤类型 过滤子类型 父节点id 数据
   */
  @Action
  public async addGraphFilter(parameters: any) {
    const response = await addFilter({
      data: {
        ...parameters,
      },
    })
    const { success, result } = response.data
    return { success, result }
  }

  /**
   * 修改过滤器
   * @param params 项目id 图id 过滤流程id 过滤类型 过滤子类型 父节点id 数据
   */
  @Action
  public async updateGraphFilter(parameters: any) {
    const response = await updateFilter({
      data: {
        ...parameters,
      },
    })
    return { success: response.data.success, result: response.data.result }
  }

  /**
   * 删除过滤器
   * @param params 项目id 图id 过滤器id
   */
  @Action
  public async deleteGraphFilter(parameters: any) {
    const response = await deleteFilter({
      data: {
        ...parameters,
      },
    })
    return { success: response.data.success }
  }

  /**
   * 查询过滤器可用属性
   * @param params 项目id 图id 过滤流程id 父节点Id
   */
  @Action
  public async queryFilterAvailableAttributes(parameters: any) {
    const response = await queryFilterAvailableAttributes({
      data: {
        ...parameters,
      },
    })
    return response.data.result
  }

  /**
   * 执行过滤流程
   * @param params 项目id 图id 过滤流程id
   */
  @Action
  public async executeFilterPipeline(parameters: any) {
    const response = await executeFilterPipeline({
      data: {
        ...parameters,
      },
    })
    return response.data
  }

  /**
   * 重置运行的过滤器
   * @param params 项目id 图id
   */
  @Action
  public async resetFilterPipeline(parameters: any) {
    const response = await resetFilterPipeline({
      data: {
        ...parameters,
      },
    })
    return { success: response.data.success }
  }

  /**
   * 删除节点和边
   */
  @Action
  public async deleteGraphItems(parameters: any) {
    const response = await deleteItems({
      data: {
        ...parameters,
      },
    })

    return { success: response.data.success }
  }

  /**
   * 更新节点和边
   */
  @Action
  public async updateGraphItems(parameters: any) {
    const response = await updateItems({
      data: {
        ...parameters,
      },
    })

    return { success: response.data.success }
  }

  /**
   * 最短路径查询
   */
  @Action
  public async queryShortestPath(parameters: any) {
    const response = await queryPath({
      data: {
        ...parameters,
      },
    })

    return response.data.result
  }

  /**
   * 搜索节点
   */
  @Action({ commit: 'setSearchResult' })
  public async searchNode(parameters: any) {
    const response = await search({
      data: {
        projectId: this.projectId,
        graphId: this.activeTabId,
        ...parameters,
      },
    })

    return response.data.result.main
  }

  /**
   * 保存到可视化
   */
  @Action
  public async saveToVis() {
    const response = await saveWidget({
      data: {
        projectId: this.projectId,
        graphId: this.activeTabId,
      },
    })

    return response
  }

  /**
   * 前进
   */
  @Action({ commit: 'setUndoRedoAction' })
  public async redoAction() {
    const response = await redo({
      data: {
        projectId: this.projectId,
        graphId: this.activeTabId,
      },
    })

    if (response.data.code !== 100) {
      message.warning(response.data.tips)
      this.setGraphAnalysisLoading(false)
      return null
    }
    return response.data.result
  }

  /**
   * 后退
   */
  @Action({ commit: 'setUndoRedoAction' })
  public async undoAction() {
    const response = await undo({
      data: {
        projectId: this.projectId,
        graphId: this.activeTabId,
      },
    })

    if (response.data.code !== 100) {
      message.warning(response.data.tips)
      return null
    }
    return response.data.result
  }

  /**
   * 查询图数据节点分类和边的分类
   * 涉及到图数据，节点数量、节点属性变化的操作需要更新该数据
   * 目前统计到的有， 图 涉及节点删除的undo redo 节点的删除，数据过滤
   */
  @Action({ commit: 'setCategoriesEdges' })
  public async queryAvailableCategory() {
    const response = await queryAvailableCategory({
      data: {
        projectId: this.projectId,
        graphId: this.activeTabId,
      },
    })
    return response.data.result
  }

  @Action({ commit: 'setHeatmapResult' })
  public async getHeatmapResult(parameters: any) {
    const response = await queryHeatMap({
      data: {
        projectId: this.projectId,
        graphId: this.activeTabId,
        ...parameters,
      },
    })
    console.log(response)

    return response.data.result
  }
}

export default getModule(GraphAnalysis)
